package com.orhanobut.logger;

import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import static com.orhanobut.logger.Utils.checkNotNull;

/**
 * CSV formatted file logging for openharmony.
 * Writes to CSV the following data:
 * epoch timestamp, ISO8601 timestamp (human-readable), log level, tag, log message.
 */
public class CsvFormatStrategy implements FormatStrategy {

  private static final String NEW_LINE = System.getProperty("line.separator");
  private static final String NEW_LINE_REPLACEMENT = " <br> ";
  private static final String SEPARATOR = ",";

  @NotNull private final Date date;
  @NotNull private final SimpleDateFormat dateFormat;
  @NotNull private final LogStrategy logStrategy;
  @Nullable private final String tag;

    private CsvFormatStrategy(@NotNull Builder builder) {
        checkNotNull(builder);
        date = builder.date;
        dateFormat = builder.dateFormat;
        logStrategy = builder.logStrategy;
        tag = builder.tag;
    }

    /**
     * newBuilder
     *
     * @return Builder
     * @noinspection checkstyle:JavadocMethod
     */
    @NotNull public static Builder newBuilder() {
        return new Builder();
    }

  @Override public void log(int priority, @Nullable String onceOnlyTag, @NotNull String message) {
    checkNotNull(message);

    String tag = formatTag(onceOnlyTag);

    date.setTime(System.currentTimeMillis());

    StringBuilder builder = new StringBuilder();

    // machine-readable date/time
    builder.append(Long.toString(date.getTime()));

    // human-readable date/time
    builder.append(SEPARATOR);
    builder.append(dateFormat.format(date));

    // level
    builder.append(SEPARATOR);
    builder.append(Utils.logLevel(priority));

    // tag
    builder.append(SEPARATOR);
    builder.append(tag);

    // message
    if (message.contains(NEW_LINE)) {
      // a new line would break the CSV format, so we replace it here
      message = message.replaceAll(NEW_LINE, NEW_LINE_REPLACEMENT);
    }
    builder.append(SEPARATOR);
    builder.append(message);

    // new line
    builder.append(NEW_LINE);

    logStrategy.log(priority, tag, builder.toString());
  }

    @Override
    public void log(int priority, @Nullable String tag, String format, Object... args) {


    }

    @Nullable private String formatTag(@Nullable String tag) {
    if (!Utils.isEmpty(tag) && !Utils.equals(this.tag, tag)) {
      return this.tag + "-" + tag;
    }
    return this.tag;
  }

    /**
     * Builder
     */
    public static final class Builder {
        private static final int MAX_BYTES = 500 * 1024; // 500K averages to a 4000 lines per file

    Date date;
    SimpleDateFormat dateFormat;
    LogStrategy logStrategy;
    String tag = "PRETTY_LOGGER";

        private Builder() {
        }

        /**
         * date
         *
         * @param val Data format Variable
         * @return Builder
         * @noinspection checkstyle:JavadocMethod
         */
        @NotNull public Builder date(@Nullable Date val) {
            date = val;
            return this;
        }

        /**
         * dateFormat
         *
         * @param val Simple Data format Variable
         * @return Builder
         * @noinspection checkstyle:JavadocMethod
         */
        @NotNull public Builder dateFormat(@Nullable SimpleDateFormat val) {
            dateFormat = val;
            return this;
        }

        /**
         * logStrategy
         *
         * @param val Simle Data format Variable
         * @return Builder
         * @noinspection checkstyle:JavadocMethod
         */
        @NotNull public Builder logStrategy(@Nullable LogStrategy val) {
            logStrategy = val;
            return this;
        }

        /**
         * tag
         *
         * @param tag String Variable
         * @return Builder
         * @noinspection checkstyle:JavadocMethod
         */
        @NotNull public Builder tag(@Nullable String tag) {
            this.tag = tag;
            return this;
        }

        /**
         * build
         *
         * @return CsvFormatStrategy
         * @noinspection checkstyle:JavadocMethod
         */
        @NotNull public CsvFormatStrategy build() {
            if (date == null) {
                date = new Date();
            }
            if (dateFormat == null) {
                dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS", Locale.UK);
            }
            if (logStrategy == null) {
                String folder = "/storage/emulated/0/" + File.separatorChar + "logger";

                String newThreadName = "FileLogger" + folder;
                EventRunner ht = EventRunner.create(newThreadName);
                EventHandler handler = new DiskLogStrategy.WriteHandler(ht, folder,
                        MAX_BYTES);
                logStrategy = new DiskLogStrategy(handler);
            }
            return new CsvFormatStrategy(this);
        }
    }
}


